﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace PacCraft
{
    class Map
    {
        public  char[][]    map;
        private Random      random;
        private Sprite3D    box;
        private Sprite3D    prism;
        public  Graph       graph;

        public Map(Model theBox, Model thePrism)
        {
            graph = new Graph();
            box = new Sprite3D(theBox);
            prism = new Sprite3D(thePrism);
            generateMap();
            graph = new Graph(this);
        }

        private void generateMap()
        {
            random = new Random();
            int sizeX = random.Next(20, 40);
            int sizeY = random.Next(20, 40);

            map = new char[sizeX][];
            for (int i = 0; i < sizeX; ++i)
                map[i] = new char[sizeY];
            for (int i = 0; i < map.Length; ++i)
                for (int j = 0; j < map[i].Length; ++j)
                {
                    if (i == 0 || j == 0 || i == sizeX - 1 || j == sizeY - 1)
                        map[i][j] = '1';
                    else
                        map[i][j] = '0';
                }
            int numberOfRooms = (sizeX + sizeY) / 3;

            for (int i = 0; i < numberOfRooms - 1; ++i)
                createRandomRoom();

            int xPrism = random.Next(1, sizeX - 1);
            int yPrism = random.Next(1, sizeY - 1);
            map[xPrism][yPrism] = '2';
            prism.position = new Vector3((float)xPrism, 2.5f, (float)yPrism);
        }

        private void createRandomRoom()
        {
            int sizeX = random.Next(4, 10);
            int sizeY = random.Next(4, 10);
            int initX = random.Next(1, map.Length - sizeX);
            int initY = random.Next(1, map[initX].Length - sizeY);

            for (int i = 0; i < sizeX && i + initX < map.Length; ++i)
                for (int j = 0; j < sizeY && j + initY < map[initX + i].Length; ++j)
                {
                    if (i == 0 || j == 0 || i == sizeX - 1 || j == sizeY - 1)
                        map[initX + i][initY + j] = '1';
                    else if (i + initX == map.Length - 1 || j + initY == map[initX + i].Length - 1)
                        map[initX + i][initY + j] = '1';
                    else
                        map[initX + i][initY + j] = '0';
                }
            //graph.createNode(initX + 1, initY + 1);
            int doorX = random.Next(1, sizeX - 1);
            int doorY = random.Next(1, sizeY - 1);
            map[initX + doorX][initY] = '0';
            map[initX][initY + doorY] = '0';
            map[initX + doorX][initY + sizeY - 1] = '0';
            map[initX + sizeX - 1][initY + doorY] = '0';
        }

        public void displayMap()
        {
            for (int i = 0; i < map.Length; ++i)
            {
                for (int j = 0; j < map[i].Length; ++j)
                    Console.Write(map[i][j]);
                Console.WriteLine(" ");
            }
        }

        public Vector2 getPrismPosition()
        {
            return new Vector2(prism.position.X, prism.position.Z);
        }

        private float getAlpha(Player player, int i, int j)
        {
            Vector2 playerPosition = player.getPosition();

            float distance = (float)Math.Sqrt(Math.Pow(playerPosition.X - i, 2) + Math.Pow(playerPosition.Y - j, 2));
            return 1 - 0.1f * distance;
        }

        private void drawMap(Player player)
        {
            for (int i = 0; i < map.Length; ++i)
                for (int j = 0; j < map[i].Length; ++j)
                {
                    box.alpha = getAlpha(player, i, j);
                    if (map[i][j] == '1')
                    {
                        for (int k = 0; k < 5; k++)
                        {
                            box.position = new Vector3((float)i, (float)k, (float)j);
                            box.Draw(player.getCamera());
                        }
                    }
                    else
                    {
                        box.position = new Vector3((float)i, 0f, (float)j);
                        box.Draw(player.getCamera());
                    }
                    if (map[i][j] == '2')
                    {
                        prism.position = new Vector3((float)i, 2.5f, (float)j);
                        prism.Draw(player.getCamera(), true);
                    }
                }
        }

        public void Draw(Player player)
        {
            drawMap(player);
        }
    }
}
